package services

import (
	"errors"
	"gitee.com/cjf8134/bbs_serve/internal/pkg/models"
	"gitee.com/cjf8134/bbs_serve/internal/pkg/requests"
	"gitee.com/cjf8134/bbs_serve/internal/pkg/responses"
	"gitee.com/cjf8134/bbs_serve/internal/pkg/utils/captchautil"
	"gitee.com/cjf8134/bbs_serve/internal/pkg/utils/constutil"
	"gitee.com/cjf8134/bbs_serve/internal/pkg/utils/emailutil"
	"gitee.com/cjf8134/bbs_serve/internal/pkg/utils/stringutil"
	"github.com/minio/minio-go"
	"go.uber.org/zap"
	"log"
	"mime"
	"mime/multipart"
	"time"
)

// GetCaptcha  图形验证码
func (s *DefaultService) GetCaptcha() (idKeyC string, base64stringC string) {
	return captchautil.GetVerifyImgString()
}

// Email  邮箱
func (s *DefaultService) Email(req *requests.Email) (err error) {
	//判断验证码是否正确
	if !captchautil.VerifyString(req.IdKeyC, req.Captcha) {
		err = errors.New("验证码输入错误")
		return
	}
	user, err := s.Repository.TestExist(&requests.TextExists{
		Key:   constutil.EmailField,
		Value: req.Email,
	})
	if err != nil || user.ID == 0 {
		err = errors.New("登陆邮箱输入错误")
		return
	}
	var (
		o = new(emailutil.Options)
	)
	if err = s.v.UnmarshalKey("smtp", o); err != nil {
		err = errors.New("unmarshal email option error")
		return
	}
	code := stringutil.GeneratorRandNumber(6)
	// 10分钟后
	mm, _ := time.ParseDuration("30m")
	err = s.Repository.Email(&models.Ems{
		Code:     code,
		Email:    user.Email,
		IP:       req.IP,
		Event:    constutil.ResetPwdEvent,
		ExpireAt: time.Now().Add(mm),
	})
	if err != nil {
		return
	}
	template, err := emailutil.SendTemplateEmail(code)
	if err != nil {
		return
	}
	err = emailutil.SendEmail(o, user.Email, constutil.CodeTitle, template)
	return
}

// ThreadList  帖子
func (s *DefaultService) ThreadList(req *requests.ThreadList) (count int64, threadList []*responses.ThreadList, err error) {
	count, list, err := s.Repository.ThreadList(req)
	if err != nil || len(list) == 0 {
		return
	}
	for _, value := range list {
		thread := &responses.ThreadList{
			ID:         value.ID,
			Title:      value.Title,
			Content:    value.Content,
			UserName:   value.Username,
			Avatar:     value.Avatar,
			ViewNum:    value.ViewNum,
			CommentNum: value.CommentNum,
			Top:        value.Top,
			Tag:        value.Tag,
			Digest:     value.Digest,
			Hot:        value.Hot,
			Comment: &responses.CommentList{
				ID:        value.Comment.ID,
				ThreadID:  value.Comment.ThreadID,
				Content:   value.Comment.Content,
				UserName:  value.Comment.Username,
				Avatar:    value.Comment.Avatar,
				ZanNum:    value.Comment.ZanNum,
				CreatedAt: value.Comment.CreatedAt.Format("2006-01-02 15:04:05"),
				UpdatedAt: value.Comment.UpdatedAt.Format("2006-01-02 15:04:05"),
			},
			CreatedAt: value.CreatedAt.Format("2006-01-02 15:04:05"),
			UpdatedAt: value.UpdatedAt.Format("2006-01-02 15:04:05"),
		}
		threadList = append(threadList, thread)
	}
	return
}

// ThreadList  帖子
func (s *DefaultService) ThreadDetail(req *requests.ThreadDetail) (thread *responses.ThreadList, err error) {
	threadModel, err := s.Repository.ThreadDetail(req)
	if err != nil || threadModel.ID == 0 {
		return
	}
	_ = s.Repository.ThreadViewNum(threadModel.ID, 1)
	thread = &responses.ThreadList{
		ID:         threadModel.ID,
		Title:      threadModel.Title,
		Content:    threadModel.Content,
		UserName:   threadModel.Username,
		Avatar:     threadModel.Avatar,
		ViewNum:    threadModel.ViewNum,
		CommentNum: threadModel.CommentNum,
		Top:        threadModel.Top,
		Tag:        threadModel.Tag,
		Digest:     threadModel.Digest,
		Hot:        threadModel.Hot,
		CreatedAt:  threadModel.CreatedAt.Format("2006-01-02 15:04:05"),
		UpdatedAt:  threadModel.UpdatedAt.Format("2006-01-02 15:04:05"),
	}
	return
}

// LinkList  友情链接列表
func (s *DefaultService) LinkList(req *requests.LinkList) (linkList []*responses.LinkList, err error) {
	list, err := s.Repository.LinkList(req)
	if err != nil || len(list) == 0 {
		return
	}
	for _, value := range list {
		link := &responses.LinkList{
			Title: value.Title,
			Desc:  value.Desc,
			Url:   value.URL,
		}
		linkList = append(linkList, link)
	}
	return
}

// Comment  回复
func (s *DefaultService) Comment(req *requests.Comment) (err error) {
	err = s.Repository.Comment(req)
	if err == nil {
		_ = s.Repository.ThreadCommentNum(req.ThreadID, 1)
		_ = s.Repository.UserScoreNum(req.Username, constutil.DefaultCommentScore)
	}
	return
}

// Thread  发表
func (s *DefaultService) Thread(req *requests.Thread) (err error) {
	err = s.Repository.Thread(req)
	if err == nil {
		_ = s.Repository.UserScoreNum(req.Username, constutil.DefaultThreadScore)
	}
	return
}

// CommentZan  点赞
func (s *DefaultService) CommentZan(req *requests.CommentZan) (err error) {
	err = s.Repository.CommentZan(req)
	if err == nil {
		_ = s.Repository.CommentZanNum(req.CommentID, 1)
	}
	return
}

// CommentZan  点赞
func (s *DefaultService) UserTotal() (int64, int64, int64) {
	return s.Repository.UserTotal()
}

// Search  搜索
func (s *DefaultService) Search(req *requests.ThreadSearch) (count int64, threadList []*responses.ThreadList, err error) {
	count, list, err := s.Repository.Search(req)
	if err != nil || len(list) == 0 {
		return
	}
	for _, value := range list {
		thread := &responses.ThreadList{
			ID:         value.ID,
			Title:      value.Title,
			Content:    value.Content,
			UserName:   value.Username,
			Avatar:     value.Avatar,
			ViewNum:    value.ViewNum,
			CommentNum: value.CommentNum,
			Top:        value.Top,
			Tag:        value.Tag,
			Digest:     value.Digest,
			Hot:        value.Hot,
			Comment: &responses.CommentList{
				ID:        value.Comment.ID,
				ThreadID:  value.Comment.ThreadID,
				Content:   value.Comment.Content,
				UserName:  value.Comment.Username,
				Avatar:    value.Comment.Avatar,
				ZanNum:    value.Comment.ZanNum,
				CreatedAt: value.Comment.CreatedAt.Format("2006-01-02 15:04:05"),
				UpdatedAt: value.Comment.UpdatedAt.Format("2006-01-02 15:04:05"),
			},
			CreatedAt: value.CreatedAt.Format("2006-01-02 15:04:05"),
			UpdatedAt: value.UpdatedAt.Format("2006-01-02 15:04:05"),
		}
		threadList = append(threadList, thread)
	}
	return
}

// CommentList  回复列表
func (s *DefaultService) CommentList(req *requests.CommentList) (commentList []*responses.CommentList, err error) {
	list, err := s.Repository.CommentList(req)
	if err != nil || len(list) == 0 {
		return
	}
	for _, value := range list {
		comment := &responses.CommentList{
			ID:        value.ID,
			ThreadID:  value.ThreadID,
			Content:   value.Content,
			UserName:  value.Username,
			Avatar:    value.Avatar,
			ZanNum:    value.ZanNum,
			CreatedAt: value.CreatedAt.Format("2006-01-02 15:04:05"),
			UpdatedAt: value.UpdatedAt.Format("2006-01-02 15:04:05"),
		}
		commentList = append(commentList, comment)
	}
	return
}

// ScoreSort  积分列表
func (s *DefaultService) ScoreSort(req *requests.ScoreSort) (scoreList []*responses.ScoreSort, err error) {
	list, err := s.Repository.ScoreSort(req)
	if err != nil || len(list) == 0 {
		return
	}
	for _, value := range list {
		score := &responses.ScoreSort{
			Username: value.Username,
			Score:    value.Score,
		}
		scoreList = append(scoreList, score)
	}
	return
}

// FileUpload  文件上传
func (s *DefaultService) FileUpload(FileHeader *multipart.FileHeader) (path string, err error) {
	log.Println(s.mioClient.Options.Bucket)
	file, err := FileHeader.Open()
	if err != nil {
		s.logger.Error("file open ", zap.Error(err))
		return
	}
	//返回文件扩展类型
	contentType := mime.TypeByExtension(FileHeader.Filename)
	size, err := s.mioClient.Mio.PutObject(s.mioClient.Options.Bucket, FileHeader.Filename, file, FileHeader.Size, minio.PutObjectOptions{ContentType: contentType})
	if err != nil {
		s.logger.Error("file Mio PutObject ", zap.Error(err))
		return
	}
	log.Printf("Successfully uploaded %s of size %d\n", FileHeader.Filename, size)
	path = "http://" + s.mioClient.Options.Endpoint + s.mioClient.Options.Bucket + "/" + FileHeader.Filename
	if s.mioClient.Options.UseSSL {
		path = "https://" + s.mioClient.Options.Endpoint + s.mioClient.Options.Bucket + "/" + FileHeader.Filename
	}
	return
}

// ThreadList  帖子
func (s *DefaultService) UserThread(req *requests.UserThread) (count int64, threadList []*responses.ThreadList, err error) {
	count, list, err := s.Repository.UserThread(req)
	if err != nil || len(list) == 0 {
		return
	}
	for _, value := range list {
		thread := &responses.ThreadList{
			ID:         value.ID,
			Title:      value.Title,
			Content:    value.Content,
			UserName:   value.Username,
			Avatar:     value.Avatar,
			ViewNum:    value.ViewNum,
			CommentNum: value.CommentNum,
			Top:        value.Top,
			Tag:        value.Tag,
			Digest:     value.Digest,
			Hot:        value.Hot,
			Comment: &responses.CommentList{
				ID:        value.Comment.ID,
				ThreadID:  value.Comment.ThreadID,
				Content:   value.Comment.Content,
				UserName:  value.Comment.Username,
				Avatar:    value.Comment.Avatar,
				ZanNum:    value.Comment.ZanNum,
				CreatedAt: value.Comment.CreatedAt.Format("2006-01-02 15:04:05"),
				UpdatedAt: value.Comment.UpdatedAt.Format("2006-01-02 15:04:05"),
			},
			CreatedAt: value.CreatedAt.Format("2006-01-02 15:04:05"),
			UpdatedAt: value.UpdatedAt.Format("2006-01-02 15:04:05"),
		}
		threadList = append(threadList, thread)
	}
	return
}
